﻿package cn.hxsteel.core.base;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import cn.hxsteel.model.vo.PageVO;

/**
 * DAO基类<持久对象的实体类,主索引键类型的实体类>，其它DAO可以直接继承这个DAO，不但可以复用共用的方法，还可以获得泛型的好处。
 */
public class BaseDAO< T, PK >
{
    private Class< T >        _entityClass;
    @Autowired
    private HibernateTemplate _hibernateTemplate;
    
    /**
     * 通过反射获取子类确定的泛型类
     */
    @SuppressWarnings( { "unchecked" } )
    public BaseDAO()
    {
	Type t = getClass().getGenericSuperclass();
	if ( t instanceof ParameterizedType )
	{
	    Type[] p = ( (ParameterizedType) t ).getActualTypeArguments();
	    _entityClass = (Class< T >) p[0];
	}
    }
    
    /* 公用方法
    --------------------------------------------------*/
    
    /**
     * 添加PO
     * 
     * @param entity 实体类
     */
    @SuppressWarnings( "unchecked" )
    public PK save( T entity )
    {
	_hibernateTemplate.getSessionFactory().getCurrentSession();
	return (PK) _hibernateTemplate.save( entity );
    }
    
    /**
     * 修改PO
     * 
     * @param entity 实体类
     */
    public void update( T entity )
    {
	_hibernateTemplate.update( entity );
    }
    
    /**
     * 删除PO
     * 
     * @param entity 实体类
     */
    public void delete( T entity )
    {
	_hibernateTemplate.delete( entity );
    }
    
    /**
     * 根据id获取PO实例
     * 
     * @param id 标识
     */
    public T get( Serializable id )
    {
	return _hibernateTemplate.get( _entityClass, id );
    }
    
    /**
     * 根据id加载PO实例
     * 
     * @param id 标识
     */
    public T load( Serializable id )
    {
	return _hibernateTemplate.load( _entityClass, id );
    }
    
    /**
     * 查询所有记录的对象列表
     */
    public List< T > loadAll()
    {
	return _hibernateTemplate.loadAll( _entityClass );
    }
    
    /* 受保护方法
    --------------------------------------------------*/
    
    /**
     * 查询对象列表
     * 
     * @param queryString 查询语句
     * @return
     */
    protected List< T > find( String queryString )
    {
	return find( _entityClass, queryString );
    }
    
    /**
     * 查询单个参数的对象列表
     * 
     * @param queryString 查询语句
     * @param value 单个参数值
     * @return
     */
    protected List< T > find( String queryString, Object value )
    {
	return find( _entityClass, queryString, value );
    }
    
    /**
     * 查询多个参数的对象列表
     * 
     * @param queryString 查询语句
     * @param values 多个参数值
     * @return
     */
    protected List< T > find( String queryString, Object... values )
    {
	return find( _entityClass, queryString, values );
    }
    
    /**
     * 查询对象列表
     * 
     * @param <E> 实体类的类型
     * 
     * @param E 实体类
     * @param queryString 查询语句
     * @return
     */
    @SuppressWarnings( "unchecked" )
    protected < E > List< E > find( Class< E > E, String queryString )
    {
	return (List< E >) _hibernateTemplate.find( queryString );
    }
    
    /**
     * 查询单个参数的对象列表
     * 
     * @param <E> 实体类的类型
     * 
     * @param E 实体类
     * @param queryString 查询语句
     * @param value 单个参数值
     * @return
     */
    @SuppressWarnings( "unchecked" )
    protected < E > List< E > find( Class< E > E, String queryString, Object value )
    {
	return (List< E >) _hibernateTemplate.find( queryString, value );
    }
    
    /**
     * 查询多个参数的对象列表
     * 
     * @param <E> 实体类的类型
     * 
     * @param E 实体类
     * @param queryString 查询语句
     * @param values 多个参数值
     * @return
     */
    @SuppressWarnings( "unchecked" )
    protected < E > List< E > find( Class< E > E, String queryString, Object... values )
    {
	return (List< E >) _hibernateTemplate.find( queryString, values );
    }
    
    /**
     * 查询多个参数的对象分页
     * 
     * @param offset 起始位置
     * @param count 查询条数
     * @param queryString 查询语句
     * @param values 多个参数值
     * @return
     */
    protected List< T > find( final int offset, final int count, final String queryString, final Object... values )
    {
	return find( _entityClass, offset, count, queryString, values );
    }
    
    /**
     * 查询多个参数的对象分页
     * 
     * @param <E> 实体类的类型
     * 
     * @param E 实体类
     * @param offset 起始位置
     * @param count 查询条数
     * @param queryString 查询语句
     * @param values 多个参数值
     * @return
     */
    @SuppressWarnings( "unchecked" )
    protected < E > List< E > find( Class< E > E, final int offset, final int count, final String queryString, final Object... values )
    {
	List< E > res = null;
	res = _hibernateTemplate.executeFind( new HibernateCallback< List< E > >() {
	    public List< E > doInHibernate( Session session )
		    throws HibernateException, SQLException
	    {
		Query query = session.createQuery( queryString );
		if ( values != null )
		{
		    for ( int i = 0; i < values.length; i++ )
		    {
			query.setParameter( i, values[i] );
		    }
		}
		List< E > result = query.setFirstResult( offset ).setMaxResults( count ).list();
		return result;
	    }
	} );
	return res;
    }
    
    /**
     * 查询多个参数的对象分页
     * 
     * @param pageNo 页码
     * @param pageSize 每页记录数
     * @param dc 独立标准
     * @return
     */
    protected PageVO< T > findPage( final int pageNo, final int pageSize, final DetachedCriteria dc )
    {
	return findPage( _entityClass, pageNo, pageSize, dc );
    }
    
    /**
     * 查询多个参数的对象分页
     * 
     * @param <E> 实体类的类型
     * 
     * @param E 实体类
     * @param pageNo 页码
     * @param pageSize 每页记录数
     * @param dc 独立标准
     * @return
     */
    protected < E > PageVO< E > findPage( Class< E > E, final int pageNo, final int pageSize, final DetachedCriteria dc )
    {
	PageVO< E > res = null;
	Criteria criteria = dc.getExecutableCriteria( _hibernateTemplate.getSessionFactory().getCurrentSession() );
	
	// 记录总数
	Integer pageRecord = (Integer) criteria.setProjection( Projections.rowCount() ).uniqueResult();
	criteria.setProjection( null );
	if ( pageRecord == 0 ) { return null; }
	
	// 数据列表
	dc.setResultTransformer( CriteriaSpecification.ROOT_ENTITY ); // 只返回根对象，不加此限制结果将返回数组，包含根对象与关联对象
	criteria.setFirstResult( ( pageNo - 1 ) * pageSize );
	criteria.setMaxResults( pageSize );
	@SuppressWarnings( "unchecked" )
	List< E > entityList = (List< E >) criteria.list();
	
	res = new PageVO< E >( pageNo, pageSize, (int) pageRecord, entityList );
	return res;
    }
    
    /**
     * 执行多个参数命令名称
     * 
     * @param queryString 命令语句
     * @param values 多个参数值
     * @return
     */
    protected boolean executeByQueryString( final String queryString, final Object... values )
    {
	boolean res = false;
	res = _hibernateTemplate.execute( new HibernateCallback< Boolean >() {
	    public Boolean doInHibernate( Session session )
		    throws HibernateException, SQLException
	    {
		Query query = session.createQuery( queryString );
		if ( values != null )
		{
		    for ( int i = 0; i < values.length; i++ )
		    {
			query.setParameter( i, values[i] );
		    }
		}
		boolean result = query.executeUpdate() > 0;
		return result;
	    }
	} );
	return res;
    }
}